<template>
    <slot :controller="controller" :store="store" :model="model">
        <div :class="classNames" :id="controlID">
            <div class="control-header app-control-calendar__header">
                <div class="app-control-calendar__header__legends">
                    <template v-for="item in model.calendarItems">
                        <div :class="{ 'app-control-calendar__header__legend': true, [item.itemType]: true, 'is-disabled': !store.isShowLegend[item.itemType] }" @click="()=>legendTrigger(item.itemType)">
                            <div class="lengend__icon" :style="'background:' + item.bKColor"></div>
                            <span class="lengend__text" :style="'color:' + item.color">{{item.name}}</span>
                        </div>
                    </template>
                </div>
            </div>    
            <div class="control-content app-control-calendar__content">
            <AppCalendar v-bind="$attrs" ref="calendar" :name="model.codeName" :class="classNames" :store="store" style="" @get-events="getEvents" @click-event="clickEvent" @render-event="renderEvent"></AppCalendar>
            </div>
        </div>
 </slot>
</template>
<script setup lang="ts">
// 基于template/src/widgets/{{appEntities}}/{{ctrls@CALENDAR}}-calendar/{{spinalCase ctrl.codeName}}-calendar-base.vue.hbs生成
import { AppCalendar } from '@components/widgets/calendar';
import { createVNode,render, Ref } from 'vue';   
import CalendarService from '@/core/modules/ctrl-service/calendar-service';
import { AppContextMenuContainer } from '@components/common/context-menu-container';
import { useProps, useBasic, useAction, useController } from './order-calendar-navigation-calendar-hook';
import { CalendarActionType, ICalendarAbility, ICalendarStore, IParam, IViewLogicInput } from "@/core/interface";

// 输入参数
const props = defineProps(useProps());


// 基础数据
const { controlID, getClassNames, model , useNavParamsBind, useEventBind, handleActionClick, handleComponentAction, handleCtrlInit, handleCtrlAction, handleCtrlDestroy} = useBasic(props);

// emit
const emit = defineEmits<{
    (event: 'ctrl-action', name: string, action: CalendarActionType, data: IParam[]): void;
    (event: 'ctrl-init', name: string, data: ICalendarAbility): void;
    (event: 'ctrl-destroy', name: string, data: IParam): void;
}>();

const evt = useEventBind(emit);
//  部件样式名
const classNames = computed(() => {
  return getClassNames(props);
});

//  日历控制器
const controller = useController(props, evt, { controlID });

useNavParamsBind(controller, props);

const store: ICalendarStore = controller.getStore();

const  { getEvents } = useAction(controller);

onMounted(() => {
    controller.ctrlMounted();
});
onUnmounted(() => {
    controller.ctrlDestroy();
})

const calendar:Ref<IParam | null>= ref(null);

// fullCalendar load时自己刷新日程
evt.on("ctrlAction", (controlName: string, action: any, data: any) => {
    if (action === 'refetchEvents') {
        refreshFullCalendar();
    }
});

// 计算日历日程样式
const handleEventStyle = (info: IParam) => {
    if (!info) {
        return;
    }
    if (calendar?.value?.fullCalendarRef) {
    const fullCalendarRef = calendar.value.fullCalendarRef;
    const data = info.event.extendedProps.$DO;
    let calendarItem = model.calendarItems.find((_item: IParam) => {
        return _item.itemType == data.itemType;
    });
    const cssName = calendarItem?.cssName;
    const calendarEvents: any[] = fullCalendarRef.getEvents().filter((event: any) => {
        return event.extendedProps.$DO[controller.getEventKey(event.extendedProps.$DO)!] === data[controller.getEventKey(info.event.extendedProps.$DO)!];
    });
    if (cssName && calendarEvents.length > 0) {
        calendarEvents.forEach((event: any) => {
            const classNames: any[] = [...event.classNames];
            if (classNames.findIndex((className: any) => { return className == cssName; }) === -1) {
                classNames.push(cssName);
                event.setProp('classNames', classNames);
            }
        })
    }
    }
}

// 刷新fullCalendar大小
const refreshFullCalendarSize = () => {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        fullCalendarRef.updateSize();
    }
}

// fullCalendar重新获取日程
const refreshFullCalendar = () => {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        fullCalendarRef.refetchEvents();
    }      
}

// 事件id
const eventid: Ref<string> = ref('');    

// 处理日历日程选中样式
const handleEventSelectStyle = ($event: any)=> {
    if (calendar?.value?.fullCalendarRef) {
        const fullCalendarRef = calendar.value.fullCalendarRef;
        if (!fullCalendarRef) {
            return;
        }
        const findApis = (id: any) => {
            if (!id) {
                return [];
            }
            return fullCalendarRef.getEvents().filter((event: any) => {
                return event.extendedProps.$DO[controller.getEventKey(event.extendedProps.$DO)!] === id;
            });
        }
        const eventId: any = $event.event.extendedProps.$DO[controller.getEventKey($event.event.extendedProps.$DO)!];
        const eventApis: any[] = findApis(eventId);
        eventApis.forEach((api: any) => {
            const classNames: any[] = [...api.classNames];
            if (classNames.findIndex((className: any) => { return className == 'selected-event'; }) === -1) {
                classNames.push('selected-event');
            }
            api.setProp('classNames', classNames);
        })
        if (props.selectFirstDefault && eventid.value != eventId || (!props.selectFirstDefault)) {
            const _eventApis: any[] = findApis(eventid.value);
            _eventApis.forEach((api: any) => {
                const _temp: any[] = [...api.classNames];
                const index = _temp.findIndex((className: any) => { return className == 'selected-event'; });
                if (index !== -1) {
                    _temp.splice(index, 1);
                    api.setProp('classNames', _temp);
                }
            })
        }
        eventid.value = eventid.value && eventid.value == eventId && !props.selectFirstDefault ? '' : eventId;
        refreshFullCalendarSize();
    }      
} 



// 点击事件
const clickEvent = (arg: IParam) => {
    controller.onEventClick(arg);
    handleEventSelectStyle(arg);     
}

// 日程绘制事件
const renderEvent = (arg: IParam) => {
    if (props.selectFirstDefault && controller.isSelectFirst) {
        clickEvent(arg);
        controller.setIsSelectFirst(false);
    }
    handleEventStyle(arg);
    let data = Object.assign({ title: arg.event.title, start: arg.event.start, end: arg.event.end }, arg.event.extendedProps);
    arg.el.addEventListener('contextmenu', (event: MouseEvent) => {
      event.preventDefault();
      let calendarItem = model.calendarItems.find((_item: any) => {
          return _item.itemType == data.itemType;
      });      
      if (calendarItem && calendarItem.contextMenus) {
        let container = document.createElement('div');
        document.body.appendChild(container);
        let vueExample = createVNode(AppContextMenuContainer, {
          contextMenus: calendarItem.contextMenus,
          onContextMenuItemClick: (args:any) => {
            if (container) {
              document.body.removeChild(container);
            }
            if (args.item) {
              controller.handleContextMenuItemClick(arg, args);
            }
          },
        });
				const appInstance = App.getUIAppInstance();
				if (appInstance) {
					vueExample.appContext = appInstance.appContext;
				}        
        render(vueExample, container); 
        if (vueExample && vueExample.component && vueExample.component.exposed) {
          vueExample.component.exposed.openMenu(event)
        }
      }
    })    
}

// 图例点击事件
const legendTrigger = (itemType: string) => {
    const eventDisabled = document.getElementsByClassName('event-disabled').length;
    if (Object.keys(store.isShowLegend).length != 1 && eventDisabled == Object.keys(store.isShowLegend).length - 1 && store.isShowLegend[itemType]) {
        return;
    }
    store.isShowLegend[itemType] = !store.isShowLegend[itemType];
    refreshFullCalendar();
}


defineExpose({
    refreshFullCalendarSize,
    refreshFullCalendar
})
</script>